import json
import os
from typing import Tuple, List, Dict, Any
from dataclasses import asdict

from .models import AppConfig, Settings, Task

CONFIG_FILENAME = "sync_config.json"


class ConfigManager:
    """配置管理器，封装配置读写逻辑"""
    
    def __init__(self):
        self._ensure_config_path()
        self._load()
    
    def _ensure_config_path(self) -> str:
        base_dir = os.getcwd()
        self.config_path = os.path.join(base_dir, CONFIG_FILENAME)
        return self.config_path
    
    def _load(self):
        """加载配置"""
        if not os.path.exists(self.config_path):
            self.config = AppConfig()
            self._save()
        else:
            with open(self.config_path, "r", encoding="utf-8") as f:
                raw = json.load(f)
            
            tasks = [_task_from_dict(t) for t in raw.get("tasks", [])]
            settings = _settings_from_dict(raw.get("settings", {}))
            self.config = AppConfig(tasks=tasks, settings=settings)
    
    def _save(self):
        """保存配置"""
        serializable = {
            "tasks": [asdict(t) | {"running": False} for t in self.config.tasks],
            "settings": asdict(self.config.settings),
        }
        # Remove ephemeral field 'running' from persistence
        for task in serializable["tasks"]:
            task.pop("running", None)
        
        with open(self.config_path, "w", encoding="utf-8") as f:
            json.dump(serializable, f, ensure_ascii=False, indent=2)
    
    def get_tasks(self) -> List[Dict[str, Any]]:
        """获取所有任务（返回字典格式）"""
        return [asdict(task) for task in self.config.tasks]
    
    def get_task(self, task_id: int) -> Dict[str, Any]:
        """根据ID获取任务"""
        for task in self.config.tasks:
            if task.id == task_id:
                return asdict(task)
        return {}
    
    def add_task(self, task_data: Dict[str, Any]):
        """添加新任务"""
        task_id = max((t.id for t in self.config.tasks), default=0) + 1
        task = Task(
            id=task_id,
            name=task_data.get("name", "未命名"),
            source_dir=task_data.get("source_dir", ""),
            target_dirs=task_data.get("target_dirs", []),
            bidirectional=task_data.get("bidirectional", False),
            enabled=task_data.get("enabled", True),
        )
        self.config.tasks.append(task)
        self._save()
    
    def update_task(self, task_id: int, task_data: Dict[str, Any]):
        """更新任务"""
        for i, task in enumerate(self.config.tasks):
            if task.id == task_id:
                self.config.tasks[i] = Task(
                    id=task_id,
                    name=task_data.get("name", task.name),
                    source_dir=task_data.get("source_dir", task.source_dir),
                    target_dirs=task_data.get("target_dirs", task.target_dirs),
                    bidirectional=task_data.get("bidirectional", task.bidirectional),
                    enabled=task_data.get("enabled", task.enabled),
                )
                self._save()
                return
    
    def delete_task(self, task_id: int):
        """删除任务"""
        self.config.tasks = [t for t in self.config.tasks if t.id != task_id]
        self._save()
    
    def get_settings(self) -> Dict[str, Any]:
        """获取设置（返回字典格式）"""
        return asdict(self.config.settings)
    
    def update_settings(self, settings: Dict[str, Any]):
        """更新设置"""
        self.config.settings = Settings(
            auto_start=settings.get("auto_start", False),
            check_interval=settings.get("check_interval", 1.0),
            log_level=settings.get("log_level", "INFO"),
            max_log_size=settings.get("max_log_size", 10 * 1024 * 1024),
            ignore_patterns=settings.get("ignore_patterns", []),
        )
        self._save()


def _ensure_config_path() -> str:
    base_dir = os.getcwd()
    return os.path.join(base_dir, CONFIG_FILENAME)


def _task_from_dict(data: dict) -> Task:
    return Task(
        id=int(data.get("id", 0)),
        name=str(data.get("name", "未命名任务")),
        source_dir=str(data.get("source_dir", "")),
        target_dirs=list(data.get("target_dirs", [])),
        bidirectional=bool(data.get("bidirectional", False)),
        enabled=bool(data.get("enabled", True)),
        running=False,
        synced_files=int(data.get("synced_files", data.get("synced", 0))),
        total_files=int(data.get("total_files", data.get("total", 0))),
    )


def _settings_from_dict(data: dict) -> Settings:
    return Settings(
        auto_start=bool(data.get("auto_start", False)),
        check_interval=float(data.get("check_interval", 1.0)),
        log_level=str(data.get("log_level", "INFO")),
        max_log_size=int(data.get("max_log_size", 10 * 1024 * 1024)),
        ignore_patterns=list(data.get(
            "ignore_patterns",
            ["*.tmp", "__pycache__/", ".git/", "node_modules/"],
        )),
    )


def load_config() -> Tuple[AppConfig, str]:
    path = _ensure_config_path()
    if not os.path.exists(path):
        default_cfg = AppConfig()
        save_config(default_cfg)
        return default_cfg, path

    with open(path, "r", encoding="utf-8") as f:
        raw = json.load(f)

    tasks = [_task_from_dict(t) for t in raw.get("tasks", [])]
    settings = _settings_from_dict(raw.get("settings", {}))
    return AppConfig(tasks=tasks, settings=settings), path


def save_config(cfg: AppConfig) -> str:
    path = _ensure_config_path()
    serializable = {
        "tasks": [asdict(t) | {"running": False} for t in cfg.tasks],
        "settings": asdict(cfg.settings),
    }
    # Remove ephemeral field 'running' from persistence
    for task in serializable["tasks"]:
        task.pop("running", None)

    with open(path, "w", encoding="utf-8") as f:
        json.dump(serializable, f, ensure_ascii=False, indent=2)
    return path
